package no.hig.ekm.ircclient;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;

import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.ListModel;
import javax.swing.AbstractListModel;
import javax.swing.event.ListDataListener;

/**
 * This class is responsible for the data displayed in the nicklist in the
 * chatWindows.
 * 
 * @author eigil
 */
public class NickList extends AbstractListModel {
	private Vector<String> data;
	ArrayList<String> nicks_o, nicks_v, nicks_m;
	
	/**
	 * Creates the highly advanced datastructure, to make it ready
	 * for use... :)
	 */
	NickList() {
		data = new Vector<String>();
	}
	
	/**
	 * Method to parse the list of nicks, sort it, and make it
	 * ready for display in the nicklist.
	 * 
	 * @param n - List of nicks, as a String.
	 */
	public void updateNicks(List<String> all, List<String> ops, List<String> voices) {
		String tmp_nick;
		
		//Sort the list alphabeticly.
		Collections.sort(all, String.CASE_INSENSITIVE_ORDER);
		Collections.sort(ops, String.CASE_INSENSITIVE_ORDER);
		Collections.sort(voices, String.CASE_INSENSITIVE_ORDER);
		
		//Create lists for the nicks, with ovn lists to ops and
		//  voice. 
		nicks_o = new ArrayList<String>(ops);
		nicks_v = new ArrayList<String>(voices);
		nicks_m = new ArrayList<String>(all);
		
		updateView();
	}

	/**
	 * Method which refreshes the overview of the nicks.
	 */
	private void updateView() {
		//Create a new datastructure, and populate it
		data = new Vector<String>();
		//First with ops
		for(int i = 0; i < nicks_o.size(); i++)
			data.add("@" + nicks_o.get(i));
		//Then voices (who not are op)
		for(int i = 0; i < nicks_v.size(); i++)
			if(!nicks_o.contains(nicks_v.get(i)))
				data.add("+" + nicks_v.get(i));
		//And finally members (which are not op nor voice)
		for(int i = 0; i < nicks_m.size(); i++)
			if(!nicks_o.contains(nicks_m.get(i)) && !nicks_v.contains(nicks_m.get(i)))
				data.add(nicks_m.get(i));
		
		fireContentsChanged(this, 0, data.size());
	}
	
	/**
	 * Updates the nicklists, and changes all occurences of "from" to "to"
	 * 
	 * @param from - The original Nick
	 * @param to - The new nick
	 */
	public void nickChanged(String from, String to) {
		for(int i = 0; i < nicks_o.size(); i++) {
			if(nicks_o.get(i).equals(from)) {
				nicks_o.remove(i);
				nicks_o.add(to);
				Collections.sort(nicks_o, String.CASE_INSENSITIVE_ORDER);
				updateView();
				return;
			}
		}
		for(int i = 0; i < nicks_v.size(); i++) {
			if(nicks_v.get(i).equals(from)) {
				nicks_v.remove(i);
				nicks_v.add(to);
				Collections.sort(nicks_v, String.CASE_INSENSITIVE_ORDER);
				updateView();
				return;
			}
		}
		for(int i = 0; i < nicks_m.size(); i++) {
			if(nicks_m.get(i).equals(from)) {
				nicks_m.remove(i);
				nicks_m.add(to);
				Collections.sort(nicks_m, String.CASE_INSENSITIVE_ORDER);
				updateView();
				return;
			}
		}
	}
	
	/**
	 * Changes the mode of a nick. Either adds, or removes a voice/op
	 * from a nick.
	 * 
	 * @param nick - The nick to change
	 * @param mode - Which mode to change (v/o)
	 * @param add - True for "+", false for "-"
	 */
	public void nickMode(String nick, char mode, boolean add) {
		if(mode == 'o' && add) {
			System.out.println("OP");
			if(!nicks_o.contains(nick)) {
				nicks_o.add(nick);
				Collections.sort(nicks_o, String.CASE_INSENSITIVE_ORDER);
			}
		} else if (mode == 'o') {
			System.out.println("DEOP");
			nicks_o.remove(nick);
		} else if(mode == 'v' && add && !nicks_o.contains(nick)) {
			System.out.println("VOICE");
			if(!nicks_v.contains(nick)) {
				nicks_v.add(nick);
				Collections.sort(nicks_v, String.CASE_INSENSITIVE_ORDER);
			}
		} else if (mode == 'v' && !nicks_o.contains(nick)) {
			System.out.println("DEVOICE");
			nicks_v.remove(nick);
		}
		
		updateView();
	}
	
	/**
	 * Adds a nick to the nicklist.
	 * 
	 * @param nick to be added
	 */
	public void add(String nick) {
		nicks_m.add(nick);
		updateView();
	}
	
	/**
	 * Removes a nick from all userlists.
	 * 
	 * @param nick to be removed
	 */
	public void remove(String nick) {
		nicks_o.remove(nick);
		nicks_v.remove(nick);
		nicks_m.remove(nick);
		updateView();
	}
	
	/**
	 * Returns a nick, with the corrospending prefix, to indicate
	 * if the user is op or voice.
	 * 
	 * @param nick to be checked
	 * @return the nick, prefixed with the right prefix.
	 */
	public String getPrefixedNick(String nick) {
		if(nicks_o.contains(nick))
			return "@" + nick;
		else if(nicks_v.contains(nick))
			return "+" + nick;
		else
			return nick;
	}

	/* (non-Javadoc)
	 * @see javax.swing.ListModel#getElementAt(int)
	 */
	@Override
	public String getElementAt(int arg0) {
		return data.get(arg0);
	}

	/* (non-Javadoc)
	 * @see javax.swing.ListModel#getSize()
	 */
	@Override
	public int getSize() {
		return data.size();
	}
}
